﻿using Basic.FormCollect;
using Basic.FormCollect.Model;
using Basic.FormModel.DB;
using Basic.FormModel.PageControl;
using Basic.FormModel.PageLayout;
using Basic.FormRemoteModel;
using Basic.FormRemoteModel.PageBody.Model;
using Basic.FormRemoteModel.PageLayout.CensusTable;
using Basic.FormRemoteModel.PageLayout.Chart;
using Basic.FormRemoteModel.PageLayout.DataTable;
using Basic.FormRemoteModel.PageLayout.Statistics;
using Basic.UserFormService.Page.Interface;
using Basic.UserFormService.PhysicsTable;
using WeDonekRpc.Helper;

namespace Basic.UserFormService.Page
{
    internal class PageStructService : IPageStructService
    {
        private readonly ICustomPageLayoutCollect _Layout;
        private readonly ICustomPageCollect _Page;
        private readonly IPageControlCollect _Control;
        private readonly IPhysicsQueryBodyCollect _QueryTable;

        public PageStructService ( ICustomPageLayoutCollect layout,
            ICustomPageCollect page,
            IPageControlCollect control,
            IPhysicsQueryBodyCollect query )
        {
            this._QueryTable = query;
            this._Control = control;
            this._Layout = layout;
            this._Page = page;
        }

        public PageBodyDto Get ( long pageId, bool isEdit )
        {
            DBCustomPage page = this._Page.Get<DBCustomPage>(pageId);
            PageLayoutDatum[] layouts = this._Layout.Gets<PageLayoutDatum>(pageId);
            if ( layouts.IsNull() )
            {
                return new PageBodyDto
                {
                    Id = pageId,
                    PageName = page.PageName,
                    PageShow = page.PageShow,
                    PageClassify = page.PageClassify
                };
            }
            long[] ids = layouts.Distinct(c => c.ControlId);
            Dictionary<long, PageControlBase> controls = this._Control.Gets(ids);
            return new PageBodyDto
            {
                Id = pageId,
                PageName = page.PageName,
                PageShow = page.PageShow,
                PageClassify = page.PageClassify,
                Controls = layouts.Convert(a => a.ParentId == 0, a => this._Format(a, controls, layouts, isEdit))
            };
        }

        public PageControlDto GetLayout ( long layoutId, bool isEdit )
        {
            PageLayoutDatumDto layout = this._Layout.Get<PageLayoutDatumDto>(layoutId);
            if ( layout.ControlType != PageControlType.容器 )
            {
                PageControlBase control = this._Control.Get<PageControlBase>(layout.ControlId);
                return this._Format(layout, new Dictionary<long, PageControlBase> {
                    { layout.ControlId, control }
                }, null, isEdit);
            }
            else
            {
                PageLayoutDatum[] children = this._Layout.GetChildren(layout.PageId, layout.Id);
                long[] ids = children.Select(a => a.ControlId).Append(layout.ControlId).ToArray();
                Dictionary<long, PageControlBase> controls = this._Control.Gets(ids);
                return this._Format(layout, controls, children, isEdit);
            }
        }
        private PageControlDto _Format ( PageLayoutDatum layout, Dictionary<long, PageControlBase> controls, PageLayoutDatum[] layouts, bool isEdit )
        {
            PageControlBase t = controls[layout.ControlId];
            PageControlDto dto = new PageControlDto
            {
                Id = layout.Id,
                ControlId = layout.ControlId,
                ControlPath = isEdit ? t.EditControlPath : t.ControlPath,
                ControlType = layout.ControlType,
                HeightGrid = layout.HeightGrid,
                WidthRatio = layout.WidthRatio,
                Name = layout.Name,
                Classify = t.Classify,
                Code = layout.Code,
                Show = layout.Show
            };
            if ( layout.ControlType == PageControlType.容器 )
            {
                dto.Layout = layout.ControlConfig?.Layout;
                dto.Children = layouts.Convert(c => c.ParentId == layout.Id, a => this._Format(a, controls, layouts, isEdit));
            }
            else if ( layout.ControlType == PageControlType.筛选组件 )
            {
                dto.Search = layout.ControlConfig?.Search;
            }
            else if ( layout.ControlType == PageControlType.普通控件 )
            {
                dto.ControlSet = layout.ControlConfig?.ControlSet;
            }
            else if ( layout.ControlType == PageControlType.图表 )
            {
                if ( layout.ControlConfig != null && layout.ControlConfig.Chart != null )
                {
                    ChartControl chart = layout.ControlConfig.Chart;
                    dto.Chart = new ChartConfig
                    {
                        FormId = chart.FormId,
                        ChartType = chart.ChartType,
                        Title = chart.Title,
                        YAxis = chart.YAxis,
                        XAxis = chart.XAxis,
                        MarkLine = chart.MarkLine.ToDictionary(a => a.ColumnId, a => a),
                        Legend = chart.Legend,
                        IsStack = chart.IsStack,
                        IsShowHead = chart.IsShowHead,
                        IsConfig = !chart.Selects.IsNull() && !chart.GroupBy.IsNull(),
                    };
                }
            }
            else if ( layout.ControlType == PageControlType.指标图 )
            {
                if ( layout.ControlConfig != null && layout.ControlConfig.Statistics != null )
                {
                    StatisticsControl control = layout.ControlConfig.Statistics;
                    dto.Statistics = new StatisticsConfig
                    {
                        FormId = control.FormId,
                        Icon = control.Icon,
                        ValueStyle = control.ValueStyle,
                        FontSize = control.FontSize,
                        Color = control.Color,
                        IsCenter = control.IsCenter,
                        IsConfig = control.FormId.HasValue && control.Select != null
                    };
                }
            }
            else if ( layout.ControlType == PageControlType.统计表 )
            {
                if ( layout.ControlConfig != null && layout.ControlConfig.CensusTable != null )
                {
                    CensusTableControl control = layout.ControlConfig.CensusTable;
                    dto.CensusTable = new CensusTableConfig
                    {
                        IsConfig = control.Selects.IsNull() != null
                    };
                }
            }
            else if ( layout.ControlType == PageControlType.明细表 )
            {
                if ( layout.ControlConfig != null && layout.ControlConfig.Table != null )
                {
                    DataTableControl control = layout.ControlConfig.Table;
                    PhysicsFormBody body = this._QueryTable.Get(control.FormId);
                    PhysicsQueryTable table = body.Main.Id == control.TableId ? body.Main : body.Children.Find(a => a.Id == control.TableId);
                    dto.Table = new TableConfig
                    {
                        FormId = control.FormId,
                        IsAction = control.IsAction,
                        Paging = control.Paging,
                        Column = table.GetColumn(control.ColumnId),
                        IsConfig = control.ColumnId.IsNull() == false
                    };
                }
            }
            return dto;
        }
        private CensusTableColDto[] _FormatCol ( CensusTableCol[] cols, List<string> mergeCol )
        {
            return cols.ConvertAll(a =>
            {
                if ( a.IsMerge.Value )
                {
                    mergeCol.Add(a.Alias);
                }
                return new CensusTableColDto
                {
                    Label = a.Label,
                    Children = a.IsGroup ? this._FormatCol(a.Children, mergeCol) : null,
                    MinWidth = a.MinWidth,
                    Align = a.Align,
                    Name = a.Alias
                };
            });
        }
    }
}
